resize_possible = True

try:
    # TRY USING OpenCV AS RESIZER
    # raise ImportError #debugging
    import cv2
    import numpy as np

    def resizer(pic, newsize):
        lx, ly = int(newsize[0]), int(newsize[1])
        if lx > pic.shape[1] or ly > pic.shape[0]:
            # For upsizing use linear for good quality & decent speed
            interpolation = cv2.INTER_LINEAR
        else:
            # For dowsizing use area to prevent aliasing
            interpolation = cv2.INTER_AREA
        return cv2.resize(+pic.astype("uint8"), (lx, ly), interpolation=interpolation)

    resizer.origin = "cv2"

except ImportError:

    try:
        # TRY USING PIL/PILLOW AS RESIZER
        from PIL import Image
        import numpy as np

        def resizer(pic, newsize):
            newsize = list(map(int, newsize))[::-1]
            shape = pic.shape
            if len(shape) == 3:
                newshape = (newsize[0], newsize[1], shape[2])
            else:
                newshape = (newsize[0], newsize[1])

            pilim = Image.fromarray(pic)
            resized_pil = pilim.resize(newsize[::-1], Image.ANTIALIAS)
            # arr = np.fromstring(resized_pil.tostring(), dtype='uint8')
            # arr.reshape(newshape)
            return np.array(resized_pil)

        resizer.origin = "PIL"

    except ImportError:
        # TRY USING SCIPY AS RESIZER
        try:
            from scipy.misc import imresize

            def resizer(pic, newsize):
                return imresize(pic, map(int, newsize[::-1]))

            resizer.origin = "Scipy"

        except ImportError:
            resize_possible = False


def resize(clip, newsize=None, height=None, width=None, apply_to_mask=True):
    """ 
    Returns a video clip that is a resized version of the clip.
    
    Parameters
    ------------
    
    newsize:
      Can be either 
        - ``(width,height)`` in pixels or a float representing
        - A scaling factor, like 0.5
        - A function of time returning one of these.
            
    width:
      width of the new clip in pixel. The height is then computed so
      that the width/height ratio is conserved. 
            
    height:
      height of the new clip in pixel. The width is then computed so
      that the width/height ratio is conserved.
    
    Examples
    ----------
             
    >>> myClip.resize( (460,720) ) # New resolution: (460,720)
    >>> myClip.resize(0.6) # width and heigth multiplied by 0.6
    >>> myClip.resize(width=800) # height computed automatically.
    >>> myClip.resize(lambda t : 1+0.02*t) # slow swelling of the clip
    
    """

    w, h = clip.size

    if newsize is not None:

        def trans_newsize(ns):

            if isinstance(ns, (int, float)):
                return [ns * w, ns * h]
            else:
                return ns

        if hasattr(newsize, "__call__"):
            # The resizing is a function of time

            def newsize2(t):
                return trans_newsize(newsize(t))

            if clip.ismask:

                def fun(gf, t):
                    return (
                        1.0 * resizer((255 * gf(t)).astype("uint8"), newsize2(t)) / 255
                    )

            else:

                def fun(gf, t):
                    return resizer(gf(t).astype("uint8"), newsize2(t))

            newclip = clip.fl(
                fun, keep_duration=True, apply_to=(["mask"] if apply_to_mask else [])
            )
            if apply_to_mask and clip.mask is not None:
                newclip.mask = resize(clip.mask, newsize, apply_to_mask=False)

            return newclip

        else:
            newsize = trans_newsize(newsize)

    elif height is not None:

        if hasattr(height, "__call__"):

            def fun(t):
                return 1.0 * int(height(t)) / h

            return resize(clip, fun)

        else:
            newsize = [w * height / h, height]

    elif width is not None:

        if hasattr(width, "__call__"):

            def fun(t):
                return 1.0 * width(t) / w

            return resize(clip, fun)

        else:
            newsize = [width, h * width / w]

    # From here, the resizing is constant (not a function of time), size=newsize

    if clip.ismask:

        def fl(pic):
            return 1.0 * resizer((255 * pic).astype("uint8"), newsize) / 255.0

    else:

        def fl(pic):
            return resizer(pic.astype("uint8"), newsize)

    newclip = clip.fl_image(fl)

    if apply_to_mask and clip.mask is not None:
        newclip.mask = resize(clip.mask, newsize, apply_to_mask=False)

    return newclip


if not resize_possible:

    doc = resize.__doc__

    def resize(clip, newsize=None, height=None, width=None):
        raise ImportError("fx resize needs OpenCV or Scipy or PIL")

    resize.__doc__ = doc
